package com.sxhuayuan.parking.compenent;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;

import com.octo.captcha.service.CaptchaService;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.sxhuayuan.parking.filter.CrossDomainFilter;
import com.sxhuayuan.parking.socket.ChannelGroupPool;
import com.sxhuayuan.parking.socket.ParkingLotInterfaceWebSocket;
import com.sxhuayuan.parking.socket.handler.ParkingLotInterfaceHandler;
import com.sxhuayuan.parking.utils.SnowFlake;

/**
 * 配置第3方bean
 *
 */
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfigureBeans {

	Logger log = LoggerFactory.getLogger(getClass());

	@Value("${spring.mvc.locale}")
	Locale locale;
	@Value("${spring.redis.host}")
	String redisHost;
	@Value("${spring.redis.port}")
	String redisPort;
	@Value("${spring.redis.password}")
	String redisPswd;

	@Bean
	public CaptchaService imageCaptchaService() {
		DefaultManageableImageCaptchaService s = new DefaultManageableImageCaptchaService();
		s.setCaptchaEngine(new CaptchaEngine());
		s.setMinGuarantedStorageDelayInSeconds(3600);
		return s;
	}

	/**
	 * 只处理短时任务，如推送http请求，更新数据库等，禁止执行大量耗时任务，会导致线程队列爆满
	 * 
	 * @return
	 */
	@Bean("taskExecutor")
	@ConfigurationProperties(prefix = "task-executor")
	public ThreadPoolTaskExecutor taskExecutorFactory() {
		ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
		threadPoolTaskExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
			@Override
			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
				log.error("taskExecutor队列已满，任务被拒绝:{}！活跃线程数={}, 最大线程数={}, 最大缓冲队列={}", r, executor.getActiveCount(), executor.getMaximumPoolSize(), executor.getQueue().size());
			}
		});
		return threadPoolTaskExecutor;
	}

	@Bean("msgQueueIdFactory")
	@ConfigurationProperties(prefix = "snow-flake.msg-queue")
	public SnowFlake msgQueueIdFactory() {
		return new SnowFlake();
	}

	@Bean("orderNoFactory")
	@ConfigurationProperties(prefix = "snow-flake.order")
	public SnowFlake orderNoFactory() {
		return new SnowFlake();
	}

	@Bean("messageSource")
	@ConfigurationProperties(prefix = "message-source")
	public ReloadableResourceBundleMessageSource messageSource() {
		return new ReloadableResourceBundleMessageSource();
	}

	@Bean("validator")
	public LocalValidatorFactoryBean validator(ReloadableResourceBundleMessageSource messageSource) {
		LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
		localValidatorFactoryBean.setValidationMessageSource(messageSource);
		return localValidatorFactoryBean;
	}

	@Bean("localeResolver")
	public FixedLocaleResolver localeResolver() {
		return new FixedLocaleResolver(locale);
	}

	@Bean
	public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
		return new OpenEntityManagerInViewFilter();
	}

	@Bean
	public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {
		FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>();
		CharacterEncodingFilter filter = new CharacterEncodingFilter("utf-8", true);
		bean.setFilter(filter);
		bean.setOrder(10);
		List<String> list = new ArrayList<>(1);
		list.add("/*");
		bean.setUrlPatterns(list);
		return bean;
	}

	@Bean
	public FilterRegistrationBean<CrossDomainFilter> crossDomainFilter() {
		FilterRegistrationBean<CrossDomainFilter> bean = new FilterRegistrationBean<>();
		CrossDomainFilter filter = new CrossDomainFilter();
		bean.setFilter(filter);
		bean.setOrder(1);
		List<String> list = new ArrayList<>(1);
		list.add("/*");
		bean.setUrlPatterns(list);
		return bean;
	}

	// @Bean(name = "redissonClient", destroyMethod = "shutdown")
	// public RedissonClient getRedissonClient() {
	// Config config = new Config();
	// config.useSingleServer().setAddress("redis://" + redisHost + ":" +
	// redisPort).setPassword(redisPswd);
	// return Redisson.create(config);
	// }

	@Bean("parkingLotInterfaceWebSocket")
	@ConfigurationProperties(prefix = "websocket.parking-lot-interface")
	public ParkingLotInterfaceWebSocket parkingLotInterfaceWebSocket() {
		return new ParkingLotInterfaceWebSocket();
	}

	@Bean("parkingLotInterfaceChannelGroupPool")
	public ChannelGroupPool ChannelGroupPool() {
		return new ChannelGroupPool();
	}

	@Bean("parkingLotInterfaceHandler")
	public ParkingLotInterfaceHandler parkingLotInterfaceHandler() {
		return new ParkingLotInterfaceHandler(ChannelGroupPool());
	}
}
